package xin.marcher.module.price.repository;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import xin.marcher.module.common.constants.price.PriceRedisKeyConstants;
import xin.marcher.module.common.enums.construction.AuditStatusEnum;
import xin.marcher.module.common.enums.construction.AuditTypeEnum;
import xin.marcher.module.common.enums.inventory.InventoryExceptionCode;
import xin.marcher.module.common.enums.price.PriceTypeEnum;
import xin.marcher.module.common.enums.price.SourceTypeEnum;
import xin.marcher.module.common.enums.seller.SellerPositionEnum;
import xin.marcher.module.common.exception.BaseBizException;
import xin.marcher.module.common.utils.JsonUtil;
import xin.marcher.module.construction.domain.dto.DraftMainDTO;
import xin.marcher.module.construction.domain.dto.SkuDetailDTO;
import xin.marcher.module.construction.domain.request.FullDraftDataRequest;
import xin.marcher.module.price.builder.FullProductData;
import xin.marcher.module.price.cache.SkuPriceCache;
import xin.marcher.module.price.converter.SkuPriceSellerRelationConverter;
import xin.marcher.module.price.domain.dto.SkuPriceSellerRelationDTO;
import xin.marcher.module.price.domain.entity.SkuInfoDO;
import xin.marcher.module.price.domain.entity.SkuPriceSellerRelationDO;
import xin.marcher.module.price.domain.request.SkuPriceRequest;
import xin.marcher.module.price.mapper.SkuPriceSellerRelationMapper;
import xin.marcher.module.price.remote.AuditRemote;
import xin.marcher.module.price.remote.ProductRemote;
import xin.marcher.module.price.remote.SellerRemote;
import xin.marcher.module.seller.domain.response.SellerInfoResponse;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 *
 */
@Repository
public class SkuPriceRepository {
    @Resource
    private SkuPriceSellerRelationMapper skuPriceSellerRelationMapper;

    @Autowired
    private AuditRemote auditRemote;

    @Autowired
    private ProductRemote productRemote;

    @Resource
    private SkuPriceSellerRelationConverter skuPriceSellerRelationConverter;

    @Autowired
    private SkuPriceCache skuPriceCache;

    @Autowired
    private SellerRemote sellerRemote;

    /**
     * 分卖家定价
     *
     * @param request
     */
    public void savePriceToDraft(SkuPriceRequest request) {
        // 校验卖家资格
        checkSeller(request);

        // 设置为手动定价
        request.setSourceType(SourceTypeEnum.MANUAL.getCode());

        // 构造请求数据
        FullDraftDataRequest fullDraftDataRequest = buildFullDraftData(request, null);

        // 保存到草稿
        auditRemote.saveDraft(fullDraftDataRequest);
    }

    /**
     * 校验卖家资格
     * 1. 卖家是否存在
     * 2. 卖家是否为城市或城市以下层级
     *
     * @param request
     */
    private void checkSeller(SkuPriceRequest request) {
        // 卖家是否存在
        List<SellerInfoResponse> sellerInfo = sellerRemote.getSellerInfo(Collections.singletonList(request.getSellerId()));
        if (CollectionUtils.isEmpty(sellerInfo)) {
            throw new BaseBizException(InventoryExceptionCode.PARAM_CHECK_ERROR, InventoryExceptionCode.PARAM_CHECK_ERROR.getErrorCode());
        }

        // 是否是城市卖家
        SellerInfoResponse sellerInfoResponse = sellerInfo.get(0);
        Integer sellerPosition = sellerInfoResponse.getSellerPosition();
        if (!sellerPosition.equals(SellerPositionEnum.CITY.getCode())) {
            throw new BaseBizException(InventoryExceptionCode.PARAM_CHECK_ERROR, InventoryExceptionCode.PARAM_CHECK_ERROR.getErrorCode());
        }
    }

    /**
     * 更新商品价格
     *
     * @param request
     */
    public void updatePriceToDraft(SkuPriceRequest request) {
        // 查询到SKU信息
        List<SkuDetailDTO> skuDetailDTOS = productRemote.listSkus(Collections.singleton(request.getSkuId()));
        // DTO 转换 DO
        List<SkuInfoDO> skuInfoDOList = skuDetailDTOS.stream()
                .map(skuDetailDTO -> skuPriceSellerRelationConverter.dtoToEntity(skuDetailDTO.getSkuInfoDTO()))
                .collect(Collectors.toList());

        // 构造请求数据
        FullDraftDataRequest fullDraftDataRequest = buildFullDraftData(request, skuInfoDOList);

        // 保存到草稿
        auditRemote.saveDraft(fullDraftDataRequest);
    }

    /**
     * 构造全量商品数据
     *
     * @param request
     * @param skuInfoDOList
     * @return
     */
    private FullDraftDataRequest buildFullDraftData(SkuPriceRequest request, List<SkuInfoDO> skuInfoDOList) {
        // 对象转换
        List<SkuPriceSellerRelationDO> skuPriceSellerRelationDOList =
                Collections.singletonList(skuPriceSellerRelationConverter.requestToEntity(request));

        FullProductData fullProductData = new FullProductData();
        // 审核的时候，依据这个字段落库价格变更记录
        fullProductData.setSkuInfoDOList(skuInfoDOList);
        // 审核的时候，依据这个字段落库价格
        fullProductData.setSkuPriceSellerRelationDOList(skuPriceSellerRelationDOList);

        // 保存到草稿
        DraftMainDTO draftMainDTO = new DraftMainDTO();
        draftMainDTO.setTicketType(AuditTypeEnum.PRICE.getCode());
        draftMainDTO.setTicketStatus(AuditStatusEnum.UNAUDITED.getCode());
        draftMainDTO.setVersionId(request.getVersionId());
        // 作为扩展字段保存到草稿
        String features = JsonUtil.object2Json(fullProductData);
        draftMainDTO.setFeatures(features);
        FullDraftDataRequest fullDraftDataRequest = new FullDraftDataRequest();
        fullDraftDataRequest.setDraftMainDO(draftMainDTO);

        return fullDraftDataRequest;
    }

    /**
     * 查询商品在某个卖家的定价
     * skuId、sellerId可以确定一件商品的价格，分为商城价和会员价
     *
     * @param request
     * @return
     */
    public List<SkuPriceSellerRelationDTO> querySkuPrice(SkuPriceRequest request) {
        // redisKey：sku_price_info:[skuId+sellerId+priceType]
        List<String> keyList = getKeyList(request);
        Optional<List<SkuPriceSellerRelationDTO>> skuPriceSellerRelationListOps = skuPriceCache.listRedisStringDataByCache(keyList,
                SkuPriceSellerRelationDTO.class,
                key -> PriceRedisKeyConstants.SKU_PRICE_INFO + key,
                request,
                req -> Optional.of(querySkuPriceFromDB(request)));
        return skuPriceSellerRelationListOps.orElse(Collections.emptyList());
    }

    /**
     * 查询商品价格，走数据库
     *
     * @param request
     * @return
     */
    private List<SkuPriceSellerRelationDTO> querySkuPriceFromDB(SkuPriceRequest request) {
        LambdaQueryWrapper<SkuPriceSellerRelationDO> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(SkuPriceSellerRelationDO::getSkuId, request.getSkuId());
        queryWrapper.eq(SkuPriceSellerRelationDO::getSellerId, request.getSellerId());
        queryWrapper.eq(SkuPriceSellerRelationDO::getPriceType, request.getPriceType());
        List<SkuPriceSellerRelationDO> skuPriceSellerRelationDOList = skuPriceSellerRelationMapper.selectList(queryWrapper);

        return skuPriceSellerRelationConverter.listEntityToDTO(skuPriceSellerRelationDOList);
    }

    /**
     * 获取redis关键字集合
     * redis的key为：sku_price_info:[skuId+sellerId+priceType]
     *
     * @param request
     * @return
     */
    private List<String> getKeyList(SkuPriceRequest request) {
        List<String> keyList = new ArrayList<>(2);
        String keyPrefix = request.getSkuId() + request.getSellerId();

        // 商城价
        if (Objects.equals(request.getPriceType(), PriceTypeEnum.BASE_PRICE.getCode())) {
            return Collections.singletonList(keyPrefix + PriceTypeEnum.BASE_PRICE.getCode());
        }
        // 会员价
        if (Objects.equals(request.getPriceType(), PriceTypeEnum.VIP_PRICE.getCode())) {
            return Collections.singletonList(keyPrefix + PriceTypeEnum.VIP_PRICE.getCode());
        }
        // 如果没有传入价格类型，则两个都进行查询
        keyList.addAll(Arrays.asList(keyPrefix + PriceTypeEnum.BASE_PRICE.getCode(), keyPrefix + PriceTypeEnum.VIP_PRICE.getCode()));
        return keyList;
    }

    /**
     * 累加版本号
     *
     * @param request
     */
    public void incrVersionId(SkuPriceRequest request) {
        // 查询出价格数据
        LambdaQueryWrapper<SkuPriceSellerRelationDO> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(SkuPriceSellerRelationDO::getSkuId, request.getSkuId());
        queryWrapper.eq(SkuPriceSellerRelationDO::getSellerId, request.getSellerId());
        queryWrapper.eq(SkuPriceSellerRelationDO::getPriceType, request.getPriceType());

        SkuPriceSellerRelationDO sellerRelationDO = skuPriceSellerRelationMapper.selectOne(queryWrapper);
        // 价格数据不存在
        if (Objects.isNull(sellerRelationDO)) {
            throw new BaseBizException(InventoryExceptionCode.PARAM_CHECK_ERROR, InventoryExceptionCode.PARAM_CHECK_ERROR.getErrorCode());
        }

        // 累加版本号
        request.setVersionId(sellerRelationDO.getVersionId() + 1);
    }

    /**
     * 填充卖家类型
     *
     * @param request
     */
    public void fillSellerType(SkuPriceRequest request) {
        // 查询卖家数据
        List<SellerInfoResponse> sellerInfo = sellerRemote.getSellerInfo(Collections.singletonList(request.getSellerId()));
        if (CollectionUtils.isEmpty(sellerInfo)) {
            throw new BaseBizException(InventoryExceptionCode.PARAM_CHECK_ERROR, InventoryExceptionCode.PARAM_CHECK_ERROR.getErrorCode());
        }

        // 设置卖家类型
        SellerInfoResponse sellerInfoResponse = sellerInfo.get(0);
        request.setSellerType(sellerInfoResponse.getSellerType());
    }

    /**
     * 检查准备修改的价格数据是否存在
     *
     * @param request
     */
    public SkuPriceRequest checkSkuPrice(SkuPriceRequest request) {
        List<SkuPriceSellerRelationDTO> priceList = querySkuPrice(request);
        if (CollectionUtils.isEmpty(priceList)) {
            throw new BaseBizException(InventoryExceptionCode.PARAM_CHECK_ERROR, InventoryExceptionCode.PARAM_CHECK_ERROR.getErrorCode());
        }

        // 原来的价格数据
        SkuPriceRequest newPrice = skuPriceSellerRelationConverter.dtoToRequest(priceList.get(0));
        newPrice.setPrice(request.getPrice());
        return newPrice;
    }
}
